home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1994 November / Cd Ware (Nro. 2) - Epimundo.iso / DOS / PG / CHART.ZIP / CSYS.86 < prev    next >
Encoding:
Text File  |  1993-11-02  |  21.9 KB  |  822 lines

  1.  
  2.         ;write error message
  3.  
  4. chart_error:
  5.         call error_exit    ;write title
  6.         db 17,'Current box must not be parent box to subchart',0
  7.  
  8.         ;write error message
  9.  
  10. open_error:
  11.         call error_exit    ;write title
  12.         db 33,'Cant open file',0
  13.  
  14.         ;load flowchart from disk
  15.  
  16. load_chart:
  17.         cmp b new_chart,0ffh    ;is there a chart in memory?
  18.         je load    ;load chart if not
  19.         mov ax,w current_box    ;load id of current box
  20.         call get_box    ;get its pointer
  21.     es    cmp w[di+child],0    ;is it the parent of a subchart?
  22.         je load    ;check if flowchart saved if not
  23.  
  24.         ;exit with error
  25.  
  26.         call chart_error    ;write error message
  27.         clc    ;indicate ok otherwise
  28.         ret    ;exit
  29. merge_chart:
  30.         mov w current_box,bp    ;store current box
  31.         call load    ;load chart
  32.         mov bp,w current_box    ;load current box
  33.         or bp,bp    ;reset chart?
  34. if ne        stc    ;exit to start of chart loop if not
  35.         ret    ;exit
  36.  
  37.         ;check if existing flowchart has been saved
  38.  
  39. load:
  40.         call tail    ;check if flowchart has been saved
  41.         jc ret    ;exit if error
  42.         call get_available_memory    ;get memory available
  43.         cmc    ;complement carry
  44.         jnc ret    ;exit if overflow
  45.         or ax,dx    ;is there any memory available?
  46.         je ret    ;exit if not
  47.         call filename_prompt    ;write prompt to bottom line
  48.  
  49.         ;get filename from user
  50.  
  51.         call get_string    ;get filename
  52.         dw filename    ;offset to string buffer
  53.         db 64,1    ;maximum string size
  54.         jnc >a1    ;open file for reading if ok
  55.         clc    ;indicate escape pressed
  56.         ret    ;exit
  57.  
  58.         ;open new chart file for reading
  59.  
  60. a1:
  61.         mov dx,si    ;load offset to filename
  62. load_chart_dx:
  63.         mov ax,03d00h    ;load function parameter
  64.         int 021h    ;create file
  65.         jnc >a1    ;subtract base if file opened
  66.         call open_error    ;write error
  67.         clc    ;indicate ok otherwise
  68.         ret    ;exit
  69.  
  70.         ;save current box and next new box markers
  71.  
  72. a1:
  73.         mov bx,ax    ;save handle
  74.         mov w handle,ax
  75.         mov ah,03fh    ;load function parameter
  76.         mov cx,4    ;load count
  77.         mov dx,o temp4    ;incase chart already loaded
  78.         int 021h    ;read current box and new box from disk
  79. if c        jmp exit_read    ;exit if error
  80.  
  81.         ;if no existing chart then initialise box markers
  82.  
  83.         mov cx,w next_box    ;load number of first new box
  84.         mov ax,w temp4    ;load current box of new chart
  85.         mov dx,first_box    ;initialise next vacant box marker
  86.         jcxz >a1    ;store current box if not
  87.         mov ax,w current_box    ;don't change current box
  88.         mov dx,cx    ;load next (old) vacant box
  89.  
  90.         ;get pointer to start of new box records
  91.  
  92. a1:
  93.         mov w temp5,ax    ;store current box
  94.         mov w next_box,dx
  95.         mov ax,w temp4+2    ;calculate number of boxes
  96.         sub ax,first_box
  97.         mov bx,box_record    ;load size of each box
  98.         mul bx    ;calculate size of boxes block
  99.         mov w temp3,ax    ;save it
  100.         mov w temp3+2,dx
  101.  
  102.         ;move existing descripter data up by size of new block
  103.  
  104.         les ax,w start_free_memory    ;load pointer to start of free memory
  105.         mov dx,es
  106.         mov w shift_count,ax    ;save it
  107.         mov w shift_count+2,dx
  108.         call get_pointer    ;calculate pointer
  109.         mov si,di    ;copy it as source pointer
  110.  
  111.         ;calculate pointer to start of descripter data new address
  112.  
  113.         add ax,w temp3    ;calculate address to end of new block
  114.         adc dx,w temp3+2
  115.         push es    ;save source segment
  116.         call get_pointer    ;calculate pointer
  117.  
  118.         ;calculate size of block
  119.  
  120.         mov ax,w next_box    ;calculate address to start of text
  121.         call get_box_address    ;get pointer to box
  122.         sub w shift_count,ax    ;calculate size of text data
  123.         sbb w shift_count+2,dx
  124.  
  125.         ;save size of existing descripter block
  126.  
  127.         mov ax,w shift_count    ;copy size of block
  128.         mov w temp2,ax
  129.         mov ax,w shift_count+2
  130.         mov w temp2+2,ax
  131.         pull ds    ;load source segment
  132.         call shift_up    ;shift descripter data up
  133.  
  134.         ;update pointers to existing descipters
  135.  
  136.         mov ds,ax,cs    ;restore data segment register
  137.         mov cx,w next_box    ;load last existing box id
  138.         les ax,w chart    ;load pointer to start of existing chart
  139.         mov dx,es
  140.         call get_pointer    ;calculate pointer
  141.         mov bx,w temp3    ;load size of new boxes block
  142.         mov dx,w temp3+2
  143.         call chart_addresses2    ;update pointers
  144.  
  145.         ;read new box data to end of existing box data
  146.  
  147.         mov ax,w temp3    ;copy size of block
  148.         mov w shift_count,ax
  149.         mov ax,w temp3+2
  150.         mov w shift_count+2,ax
  151.         mov ax,w next_box    ;calculate pointer to start of new block
  152.         call get_box_address    ;get pointer to box
  153.         call read_block    ;read box data from disk
  154.         jc >e1    ;abort chart if error
  155.  
  156.         ;read remaining new data to end of old descripter data
  157.  
  158.         mov ax,w start_free_memory    ;load address to end of data
  159.         mov dx,w start_free_memory+2
  160.         mov w shift_count+2,-1    ;read to end of file
  161.         call read_block    ;read descripter text data from disk
  162.         jnc >a1    ;link chart if loaded ok
  163. e1:
  164.         mov w current_box,0    ;indicate error and clear chart
  165.         ret    ;exit
  166.  
  167.         ;link new chart to existing chart
  168.  
  169. a1:
  170.         mov ax,w current_box    ;load current box
  171.         call get_box    ;get pointer to it
  172.         mov ax,w next_box    ;load id of first box in new chart
  173.     es    mov w[di+child],ax    ;link charts
  174.  
  175.         ;update parent pointers for current box
  176.  
  177.         mov bp,ax    ;calculate number of existing boxes
  178.         sub bp,first_box
  179.         call get_box_address    ;get pointer to box
  180.         call get_pointer    ;calculate pointer
  181.         add w temp2,ax    ;calculate offset to start of new
  182.         adc w temp2+2,dx    ;descripter strings
  183.  
  184.         ;calculate number of new boxes
  185.  
  186.         mov cx,w temp4+2    ;calculate number of new boxes
  187.         sub cx,first_box
  188.         add w next_box,cx    ;add new boxes to existing boxes
  189.         mov ds,ax,es    ;copy pointer to boxes
  190.         mov si,di
  191.  
  192.         ;check basic route slots
  193.  
  194. b1:
  195.         mov bx,previous    ;load offset to 'previous' route slot
  196.         call update_slot    ;check if slot points to another box
  197.         mov bx,yes    ;check yes route slot
  198.         call update_slot    ;check if slot points to another box
  199.         mov bx,no    ;check no route slot
  200.         call update_slot    ;check if slot points to another box
  201.  
  202.         ;if parent route is vacant, point it to current box of existing chart
  203.  
  204.         mov bx,parent    ;load offset to 'parent' route slot
  205.         cmp w[si+bx],0    ;is box on top level of new chart?
  206.         mov ax,bp    ;assume it isn't
  207. if e    cs    mov ax,w current_box    ;point it to current box if it is
  208.         add w[si+bx],ax    ;update child route slot
  209.  
  210.         ;update child route and pointer to descripter
  211.  
  212.         mov bx,child    ;load offset to 'child' route slot
  213.         call update_slot    ;check if slot points to another box
  214.         mov bx,descripter    ;load offest to descripter pointer
  215.     cs    mov ax,w temp2    ;load base address for desripter
  216.         add w[si+bx],ax    ;add it to offset
  217.     cs    mov ax,w temp2+2
  218.         adc w[si+bx+2],ax
  219.  
  220.         ;move to next box record
  221.  
  222.         cmp si,0fc00h    ;is there reasonable room above
  223.         jb >a1    ;update numbers if there is
  224.         sub si,08000h    ;normalise pointer
  225.         mov ax,ds
  226.         add ax,0800h
  227.         mov ds,ax
  228. a1:
  229.         add si,box_record    ;move to next record
  230.         loop b1    ;decrement loop count
  231.  
  232.         ;update current box
  233.  
  234.         mov ds,ax,cs    ;copy segment to workspace
  235.         mov ax,w temp5    ;copy current box
  236.         mov w current_box,ax
  237.  
  238.         ;reset chart variables
  239.  
  240.         xor ax,ax    ;clear register
  241.         mov b chart_flag,4    ;set chart entry flag
  242.         mov b box_made,0ffh    ;dont create a box
  243.         mov b new_chart,080h    ;indicate chart loaded
  244.         mov w key_option,ax    ;clear key option flag
  245.         mov w box_save,ax    ;clear flag/box store
  246.         mov w insert_mode,ax    ;clear flag
  247.         mov w link_box,ax    ;clear link box
  248.         mov w box_to_subchart,ax    ;clear flag
  249.         mov w subchart_link,ax    ;clear subchart follow box
  250.         mov w sub_stack,top_stack    ;clear stack
  251.         mov b message,al    ;clear message buffer
  252.  
  253.         ;close file and exit
  254.  
  255.         call chart_bookmarks    ;copy any bookmarks to table
  256.         call close_input_file    ;close file
  257.         clc    ;indicate all ok
  258.         ret    ;exit
  259.  
  260.         ;update box slot
  261.  
  262. update_slot:
  263.         cmp w[si+bx],first_box    ;does slot route point to another box?
  264. if ae        add w[si+bx],bp    ;update it if it does
  265.         ret    ;exit
  266.  
  267.         ;convert segment:offset (ax:si) to 20 bit address
  268.  
  269. ptr_addr:
  270.         xor dx,dx    ;clear high order nibble of source addr
  271.         shl ax,1    ;store high order nibble of segment
  272.         rcl dl,1    ;value into al
  273.         shl ax,1
  274.         rcl dl,1
  275.         shl ax,1
  276.         rcl dl,1
  277.         shl ax,1
  278.         rcl dl,1
  279.         add ax,si    ;calculate low word of address
  280.         adc dl,dh    ;add carry to high order nibble
  281.         ret    ;return
  282.  
  283.         ;exit with error
  284.  
  285. e1:
  286.         call close_input_file    ;close file
  287. memory_error:
  288.         call error_exit    ;exit with error
  289.         db 30,'insufficient memory',0
  290.  
  291.         ;calculate memory available
  292.  
  293. get_available_memory:
  294.         mov ax,w ram_top    ;load address to end of free memory
  295.         mov dx,w ram_top+2
  296.         sub ax,w start_free_memory    ;subtract base of free memory
  297.         sbb dx,w start_free_memory+2
  298.         ret    ;exit
  299.  
  300.         ;read data from disk
  301.         ;calculate memory available
  302.  
  303. read_block:
  304.         mov w temp1,ax    ;save address to start of block
  305.         mov w temp1+2,dx
  306. b1:
  307.         mov ax,w temp1    ;load address to start of block
  308.         mov dx,w temp1+2
  309.         call get_pointer    ;convert address to pointer
  310.  
  311.         ;range check pointer
  312.  
  313.         call load_count    ;load byte count
  314.         call get_available_memory    ;get memory available
  315.         or dx,dx    ;is there enough memory?
  316.         jne >a1    ;load block if there is
  317.         cmp ax,cx    ;is there enough memory?
  318. if be        mov cx,ax    ;load block if there is
  319.         or ax,ax    ;is there any available memory?
  320.         je e1    ;exit if not
  321.  
  322.         ;range check pointer
  323.  
  324. a1:
  325.         call range_check_dptr    ;range check pointer
  326.         mov dx,di    ;load offset
  327.         mov ax,es    ;copy segment
  328.         mov bx,w handle    ;load handle
  329.         mov ds,ax
  330.         mov ah,03fh    ;load function parameter
  331.         int 021h    ;read block from disk
  332.         mov ds,di,cs    ;restore data segment register
  333.         jnc >a1    ;check if all bytes were read if ok
  334.  
  335.         ;close file and exit with error message
  336.  
  337. exit_read:
  338.         call close_input_file    ;close file
  339.         call error_exit    ;exit with error
  340.         db 30,'Cant read from disk',0
  341.  
  342.         ;check if any bytes were read
  343.  
  344. a1:
  345.         add w start_free_memory,ax    ;add bytes read to address
  346.         adc w start_free_memory+2,0
  347.         add w temp1,ax    ;add to offset to start of last block
  348.         adc w temp1+2,0
  349.         or ax,ax    ;were any bytes read?
  350.         jne b1    ;read next block if there were
  351.         ret    ;exit
  352.  
  353.         ;close input file
  354.  
  355. close_input_file:
  356.         mov ah,03eh    ;load function paramter
  357.     cs    mov bx,w handle    ;load input handle
  358.         int 021h    ;close file
  359.         ret    ;exit
  360.  
  361.         ;goto dos shell
  362.  
  363. dos_shell:
  364.         call cls    ;clear the screen
  365.         call writexy    ;write message
  366.         db 14,21
  367.         db 'Please enter amount of memory to reserve for Chart.',0
  368.         call writexy
  369.         db 26,22
  370.         db 'Minimum required ',0
  371.  
  372.         ;calculate minimum bytes required
  373.  
  374.         mov ax,cs    ;load code segment
  375.         mov bx,16    ;multiply it by 16
  376.         mul bx
  377.         mov bx,w start_free_memory    ;load top of memory address
  378.         mov cx,w start_free_memory+2
  379.         sub bx,ax    ;calculate minimum bytes needed
  380.         sbb cx,dx
  381.         add bx,02010h    ;add 8k bytes needed for stacks
  382.         adc cx,0
  383.         mov ax,bx    ;convert number to string
  384.         mov dx,cx
  385.         mov w reserve,ax    ;save it
  386.         mov w reserve+2,dx
  387.  
  388.         ;write bytes required to screen
  389.  
  390.         mov di,o s    ;load offset to buffer
  391.         call store_number3    ;convert required bytes to string
  392.         mov cx,di    ;calculate size of string
  393.         mov di,o left_route    ;load destination buffer offset
  394.         sub cx,o s
  395. a1:
  396.         std    ;read backwards
  397.         lodsb    ;load character from string
  398.         cld    ;write forwards
  399.         stosb
  400.         call write_chr    ;write it to screen
  401.         loop a1    ;decrement loop count
  402.         xor al,al    ;terminate string
  403.         stosb
  404.         call write    ;write bytes message
  405.         db ' bytes.',0
  406.  
  407.         ;get minimum bytes required from user
  408.  
  409.         call get_string    ;get bytes required
  410.         dw left_route
  411.         db 7,1
  412. if c        jmp body    ;exit to menu if escape pressed
  413.  
  414.         ;convert ascii digits to binary
  415.  
  416.         call get_val    ;convert string to number
  417.         jc >a2    ;prompt again if error
  418.         cmp dx,w reserve+2    ;is amount too small?
  419.         ja >a1    ;reserve bytes if not
  420.         jb >a2    ;reprompt if it is
  421.         cmp ax,w reserve    ;is amount too small?
  422.         jae >a1    ;reserve bytes if not
  423. a2:
  424.         jmp dos_shell    ;reprompt if it is
  425.  
  426.         ;save program size
  427.  
  428. a1:
  429.         mov bx,ax    ;save bytes to reserve
  430.         mov cx,dx
  431.         mov ax,cs    ;calculate address to start of program
  432.         xor si,si
  433.         call ptr_addr    ;convert pointer to address
  434.         add ax,bx    ;add size of program
  435.         adc dx,cx
  436.         sub ax,32    ;allow for paragraph overlap
  437.         sbb dx,0
  438.         mov w ram_top,ax    ;mark end of program
  439.         mov w ram_top+2,dx
  440.  
  441.         ;resize program and data
  442.  
  443.         shr cx,1    ;convert 20 bit address to segment
  444.         rcr bx,1
  445.         shr cx,1
  446.         rcr bx,1
  447.         shr cx,1
  448.         rcr bx,1
  449.         shr cx,1
  450.         rcr bx,1
  451.  
  452.         ;resize program
  453.  
  454.         mov w end_stack,bx    ;save it
  455.         add bx,010h    ;add a paragraph
  456.         mov es,ax,cs    ;copy base segment
  457.         mov ah,04ah    ;load function parameter
  458.         int 021h    ;resize memory allocation
  459.  
  460.         ;write exit message
  461.  
  462.         call writexy    ;write prompt
  463.         db 1,11
  464.         db 'Type EXIT to return to Chart',0
  465.  
  466.         ;get comspec filename
  467.  
  468.         mov es,w[02ch]    ;load segment to environment block
  469.         xor di,di    ;load offset
  470.         xor al,al
  471. a1:
  472.         mov si,o comspec_string    ;load offset to comspec search string
  473.         mov cx,8    ;load length of string
  474.         repe
  475.         cmpsb    ;compare strings
  476.         je >a2    ;load offset to comspec if found
  477.  
  478.         ;move to next entry
  479.  
  480.         mov cx,08000h    ;load maximum environment block size
  481.         repne
  482.         scasb    ;scan to end of environment string
  483.     es    cmp b[di],0    ;end of environment block?
  484.         jne a1    ;check next environment string if not
  485.  
  486.         ;write error message
  487.  
  488.         call writexy    ;write can't load comspec message
  489.         db 1,13
  490.         db 'Cannot find COMSPEC, press ESC',0
  491. a4:
  492.         call key    ;fetch keypress
  493.     cs    mov b middle_5,0    ;cancel quick exit flag
  494.         jc a4    ;get another keypress if middle 5 down
  495.         jne a4    ;fetch another keypress if not escape
  496.         jmp long >b1    ;resize program block
  497.  
  498.         ;initialise parameter block for exec function
  499.  
  500. a2:
  501.         call restore_cursor    ;restore cursor type
  502.         mov dx,di    ;load offset to comspec filename
  503.         mov es,bx,cs    ;load code segment
  504.  
  505.         ;initialise file control blocks
  506.  
  507.         mov di,o s    ;load offset to fcb #1
  508.         mov si,o fcb    ;load offset to fcb string
  509.         mov ax,02901    ;load function parameters
  510.         int 021h    ;format fcb #1
  511.         mov ds,ax,cs    ;restore segment register
  512.         mov di,o s+010h    ;load offset to fcb #2
  513.         mov si,o fcb    ;load offset to fcb string
  514.         mov ax,02901    ;load function parameters
  515.         int 021h    ;format fcb #2
  516.  
  517.         ;point keyboard interrupt to interrupt handler
  518.  
  519.         push dx    ;save offset to comspec
  520.         mov ax,03509h    ;load function parameter and interrupt
  521.         int 021h    ;get interrupt handler
  522.         mov ds,ax,cs    ;restore segment register
  523.         mov w interrupt_exit,bx    ;save offset
  524.         mov w interrupt_exit+2,es    ;save segment
  525.         mov ax,02509h    ;load parameter and interrupt number
  526.         mov dx,o interrupt_entry    ;load offset to interrupt handler
  527.         int 021h    ;point interrupt
  528.  
  529.         ;initialise parameter block
  530.  
  531.         mov w >e5,cs    ;store segment address of program
  532.         mov w >e5+4,cs
  533.         mov w >e5+8,cs
  534.  
  535.         ;set up temporary stack
  536.  
  537.         pull dx    ;restore offset to comspec
  538.         mov es,ax,cs    ;load code segment
  539.         mov bx,o >e3    ;load offset
  540.         add ax,w end_stack    ;add program size
  541.         sub ax,01010h    ;subtract a segment
  542.         cli    ;disable interrupts
  543.         mov sp,-2    ;load offset to temporary stack
  544.         mov ss,ax    ;load segment to temporary stack
  545.         sub ax,0100h    ;calculate box stack segment
  546.         mov w stack_segment,ax    ;store it
  547.  
  548.         ;call comspec
  549.  
  550.         mov b chart_active,0    ;indicate chart in dos shell
  551.         mov b direct_video,-1    ;don't write through bios
  552.         mov ds,w[02ch]    ;load segment to comspec filename
  553.         mov ax,04b00h    ;load function parameters
  554.         sti    ;enable interrupts
  555.         int 021h    ;call comspec
  556.         mov ds,ax,cs    ;restore segment registers
  557.         mov es,ax
  558.         mov b chart_active,0ffh    ;indicate chart in op
  559.         jnc >b2    ;exit if ok
  560.  
  561.         ;write error message
  562.  
  563.         call writexy    ;write can't load comspec message
  564.         db 1,13
  565.         db 'Cannot load COMSPEC, press ESC',0
  566. a4:
  567.         call key    ;fetch keypress
  568.     cs    mov b middle_5,0    ;cancel quick exit flag
  569.         jc a4    ;get another keypress if middle 5 down
  570.         jne a4    ;fetch another keypress if not escape
  571.  
  572.         ;point keyboard interrupt to interrupt handler
  573.  
  574. b2:
  575.         mov ax,02509h    ;load parameter and interrupt number
  576.     cs    lds dx,w interrupt_exit    ;load offset to old interrupt handler
  577.         int 021h    ;restore interrupt
  578.         mov ds,ax,cs    ;restore data segment register
  579.         sti    ;enable interrupts
  580.  
  581.         ;check if enough memory to continue
  582.  
  583. b1:
  584.         call init_screen    ;set screen mode
  585.         mov bx,w[2]    ;load ram top
  586.         mov ax,cs    ;load code segment
  587.         sub bx,ax    ;calculate original block size
  588.         push bx    ;save block
  589.         mov es,ax    ;load base segment
  590.         mov ah,04ah    ;load function parameter
  591.         int 021h    ;resize allocated memory
  592.         jnc >b1    ;restore stack pointer if ok
  593.  
  594.         ;set stack pointer as it was when comspec was called
  595.  
  596.         pull ax    ;clear old block from stack
  597.         push bx    ;save maximum paragraphs free
  598.         mov ah,04ah    ;load parameter
  599.         int 021h    ;get maximum bytes
  600. b1:
  601.         pull ax    ;load block size allocated
  602.         mov bx,cs    ;load base segment
  603.         add ax,bx    ;calculate stack segment
  604.         sub ax,01000h
  605.         mov ss,ax
  606.         mov bx,ax    ;copy segment
  607.         sub bx,0100h    ;calculate box stack segment
  608.         mov w stack_segment,bx
  609.         mov sp,-2
  610.  
  611.         ;restore ram top
  612.  
  613.         xor si,si    ;convert stack pointer to address
  614.         call ptr_addr
  615.         mov w ram_top,ax    ;save it
  616.         mov w ram_top+2,dx
  617.         jmp main    ;join main loop
  618.  
  619.         ;exec funtion parameter block
  620.  
  621. comspec_string db 'COMSPEC=',0    ;dos shell comspec string in environment
  622.             ;block
  623.  
  624. e3 dw 0        ;segment address of environment block
  625.    dw >e4    ;offset of command tail
  626. e5 dw ?        ;segment of command tail
  627.    dw offset s    ;segment:offset of fcb #1
  628.    dw ?
  629.    dw offset s+010h    ;segment:offset of fcb #2
  630.    dw ?
  631.  
  632. e4 db 0        ;command tail passed to dos shell
  633. fcb db 13
  634.  
  635. interrupt_exit dw 2 dup ?    ;exit address for interrupt
  636.  
  637.         ;check if keypress is middle 5 of keypad (with num-lock off)
  638.  
  639. b1:
  640.         stc    ;indicate key not down
  641.         ret    ;exit
  642. check_mid_5:
  643.         in al,060h    ;get key scan code
  644.         cmp al,04ch    ;is it middle 5 in keypad?
  645.         jne b1    ;exit if not
  646.         xor ax,ax    ;load base segment
  647.         mov ds,ax
  648.         test b[0417],020h    ;is num lock on?
  649.         jne b1    ;exit if it is
  650.  
  651.         ;send acknowledge signal
  652.  
  653.         in al,61h    ;read 8255 port pb
  654.         or al,80h    ;set ack signal
  655.         out 61h,al    ;send ack signal
  656.         and al,7fh    ;reset keyb ack
  657.         out 61h,al    ;and 8255 port pb
  658.         mov al,20h    ;notify int cntrllr
  659.         out 20h,al
  660.         clc    ;indicate key pressed
  661.         ret    ;exit
  662.  
  663.         ;exit from handler
  664.  
  665. b2:
  666.         pull ds,ax    ;restore registers
  667. b1:
  668.     cs    jmp d[interrupt_exit]    ;exit
  669.  
  670.         ;keyboard interrupt handler
  671.  
  672. interrupt_entry:
  673.     cs    cmp b chart_active,080h    ;is chart in dos shell?
  674.         ja b1    ;exit if not
  675.         push ax,ds    ;save registers
  676.         jb >a1    ;check keypress if first call from shell
  677.         call check_mid_5    ;check if middle 5 of key pad pressed
  678.         jc b2    ;exit if not down
  679.     cs    mov b middle_5,0ffh    ;indicate middle 5 is down
  680.         jmp b2    ;exit
  681.  
  682.         ;check if foreground process is msdos
  683.  
  684. a1:
  685.         call check_mid_5    ;check if middle 5 of key pad pressed
  686.         jc b2    ;exit if not down
  687.         push bx,cx,dx,si,di,bp,es    ;save remainder of registers
  688.         mov ax,w[0463h]    ;load current crtc port address
  689.     cs    xchg w crtc_address,ax    ;swap with secondary address
  690.         push ax    ;save port address to chart display
  691.         mov ds,ax,cs    ;copy code segment
  692.         mov es,ax
  693.         sti    ;enable interrupts
  694.         mov b chart_active,080h    ;indicate chart in op
  695.  
  696.         ;get pointers to video map
  697.  
  698.         call get_screen    ;get screen pointer
  699.         mov w display_match,ax    ;save screen types
  700.         mov w cursor_data,dx    ;save cursor coordinates
  701.         mov w cursor_type,cx    ;save cursor type
  702.         call clear_cursor    ;clear cursor from user screen
  703.         pull ax    ;load port address of chart display
  704.         xchg w crtc_address,ax    ;restore crtc address for chart display
  705.         push ax    ;save port address to current display
  706.  
  707.         ;check if current display mode will be overwritten
  708.  
  709.         xor dx,dx    ;move pointer to start of video map
  710.         call cursor    ;position cursor
  711.         mov ax,w display_match    ;load both display types
  712.         cmp al,ah    ;are we overwriting the calling screen?
  713.         je >a2    ;save screen if yes
  714.         cmp b middle_5,0    ;did chart last exit from editor?
  715.         jne >a1    ;set up stack if not
  716.  
  717.         ;backup video
  718.  
  719. a2:
  720.         lds si,w video_pointer    ;load pointer to start of map
  721.     cs    mov w saved_screen,si    ;save it
  722.     cs    mov w saved_screen+2,ds
  723.         mov di,o video_backup    ;load pointer to backup
  724.         mov cx,2000    ;load size of screen map in words
  725.         rep
  726.         movsw    ;backup screen
  727.  
  728.         ;set up stack
  729.  
  730. a1:
  731.         mov bx,sp    ;save state of stack
  732.         mov cx,ss
  733.         mov ds,ax,cs    ;copy code segment
  734.         add ax,w end_stack    ;add program size
  735.         sub ax,01010h    ;subtract a segment
  736.         cli    ;disable interrupts
  737.         mov sp,-2    ;load offset to temporary stack
  738.         mov ss,ax    ;load segment to temporary stack
  739.  
  740.         ;save pointer to video map data
  741.  
  742.         push bx,cx    ;save pointer
  743.         sti    ;re-enable interrupts
  744.         mov w sub_stack,top_stack    ;clear stack
  745.         sub ax,0100h    ;allow 4k for stack
  746.         mov w stack_segment,ax
  747.  
  748.         ;call chart
  749.  
  750.         xor al,al    ;load zero
  751.         xchg b middle_5,al    ;indicate calling menu level
  752.         mov bp,w current_box    ;load current box
  753.         or al,al    ;was middle 5 down
  754.         je >a1    ;call main menu if not
  755.  
  756.         ;call editing level
  757.  
  758.         call clear_cursor    ;clear cursor from user screen
  759.         call flowchart    ;call at editor level if it was
  760.         jc >a2    ;exit if middle 5 pressed
  761. a1:
  762.         call body    ;call menu level
  763.  
  764.         ;restore stack
  765.  
  766. a2:
  767.         mov ds,ax,cs    ;copy segment to workspace
  768.         pull dx,ax    ;restore stack pointer
  769.         cli    ;disable interrupts
  770.         mov sp,ax    ;restore offset to calling stack
  771.         mov ss,dx    ;restore segment to calling stack
  772.         sti    ;re-enable interrupts
  773.  
  774.         ;if display was overwritten the restore it's original state
  775.  
  776.         mov ax,w display_match    ;load screen types
  777.         cmp al,ah    ;are we overwriting the calling screen?
  778.         je >a2    ;save screen if yes
  779.         cmp b middle_5,0    ;restore user screen?
  780.         jne >a1    ;exit if not
  781.  
  782.         ;restore screen display map
  783.  
  784. a2:
  785.         les di,w saved_screen    ;load pointer to map
  786.         mov si,o video_backup    ;load pointer to backup map
  787.         mov cx,2000    ;load size of map
  788.         rep
  789.         movsw    ;restore video
  790.  
  791.         ;restore cursor state and position
  792.  
  793. a1:
  794.         xor ax,ax    ;load zero
  795.         mov es,ax
  796.     es    mov al,b[0462h]    ;load video page
  797.         mov b active_page,al    ;store page
  798.         call clear_cursor    ;clear cursor from user screen
  799.         pull ax    ;load port address of chart display
  800.         xchg w crtc_address,ax    ;restore crtc address for chart display
  801.         push ax    ;save port address to current display
  802.  
  803.         ;restore cursor state and position
  804.  
  805.         mov cx,w cursor_type    ;save cursor type
  806.         call set_cursor    ;clear cursor from user screen
  807.         mov dx,w cursor_data    ;save cursor coordinates
  808.         call cursor    ;position cursor
  809.         pull w crtc_address    ;restore crtc address for chart display
  810.         mov b chart_active,0    ;indicate chart not in op
  811.         pull es,bp,di,si,dx,cx,bx,ds,ax    ;restore registers
  812.         iret    ;exit
  813.  
  814.         ;check if safe to call BIOS
  815.  
  816. int10:
  817.     cs    cmp b chart_active,080h    ;is chart in dos shell?
  818. if ne        int 010h    ;call BIOS if not
  819.         ret    ;exit        
  820.  
  821.         ;end
  822.